Skip to content

fix(core): bypass gray-matter content cache when parsing frontmatter - #51245

Merged
rekram1-node merged 1 commit into
anomalyco:v2from
holny:fix-51218-matter-cache
Oct 7, 2026
Merged

rekram1-node merged 1 commit into
anomalyco:v2from
holny:fix-51218-matter-cache

Conversation

@holny

@holny holny commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Issue for this PR

Closes #51218

Type of change

  • Bug fix

What does this PR do?

gray-matter writes to its module-global content cache before parsing (matter.cache[file.content] = file runs ahead of parseMatter), so a failed YAML parse leaves a poisoned cache entry with no usable data. Every later matter() call with the same content returns that entry without throwing — which is exactly what ConfigMarkdown.parse does: the first load in a server process could sanitize an unquoted-colon frontmatter correctly via the fallback, but every subsequent instance init replayed the poisoned entry, never threw, and the skill was silently dropped by the empty-data check upstream. Upstream report: jonschlinkert/gray-matter#166 (open since 2023).

Passing an options object bypasses the cache read and write (gray-matter only caches when called with no options), so every parse is deterministic and the sanitize() fallback recovers on each load. One-line change plus a regression test.

How did you verify your code works?

  • New packages/core/test/config/markdown.test.ts with 4 cases: sanitize fallback recovery, repeat-parse recovery after a failed parse, repeated throws for genuinely unparseable content, and plain no-frontmatter content. Red/green checked: the old uncached call fails 2 of the 4, the fix passes all 4.
  • bun test test/config/markdown.test.ts test/config/skill.test.ts test/config/command.test.ts is 42 pass / 0 fail.
  • bun typecheck clean.

Screenshots / recordings

Not a UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Closes #51218

gray-matter populates its module-global content cache before parsing, so
a failed YAML parse leaves a poisoned entry and every later parse of the
same content returns it without throwing. In a long-lived serve process
the first config load could sanitize an unquoted-colon frontmatter
correctly, but every later instance init replayed the poisoned entry,
never threw, and the skill was silently dropped by the empty-data check
upstream.

Passing an options object bypasses the cache read and write (gray-matter
only caches when called with no options), making every parse
deterministic and letting the sanitize fallback recover on each load.

Regression test covers the repeat-parse recovery, the repeated throw for
genuinely unparseable content, and plain content.

Fixes anomalyco#51218
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants